﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Reflection;
using System.Text;

using vJine.Core.Base;
using vJine.Core.IoC;
using vJine.Core.ORM.Adapters;

namespace vJine.Core.ORM {
    /// <summary>
    /// 数据库操作类
    /// </summary>
    public partial class DataManager : EntityBase, IDisposable {

        #region Init & Dispose

        /// <summary>
        /// 创建DataManager实例(按应用程序配置文件中的Default）
        /// </summary>
        public DataManager() 
            : this(null, "Default", null) {
        }

        /// <summary>
        /// 创建DataManager实例（按应用程序配置文件）
        /// </summary>
        /// <param name="name">数据库配置节名称</param>
        /// <param name="connectionString">数据库连接字符串，如果不指定则取配置文件中的值</param>
        public DataManager(string name, string connectionString = null)
            : this(OrmConfig.My, name, connectionString) {
        }

        /// <summary>
        /// 创建DataManager实例
        /// </summary>
        /// <param name="ormConfig">用户自定义配置文件</param>
        /// <param name="name">数据库配置节名称</param>
        /// <param name="connectionString">数据库连接字符串，如果不指定则取配置文件中的值</param>
        DataManager(OrmConfig ormConfig, string name, string connectionString = null) {

            this.session_id = this.GetHashCode();

            if (string.IsNullOrEmpty(name)) {
                throw new ArgumentNullException("name");
            }

            ormConfig = ormConfig ?? OrmConfig.My;

            OrmConfig.db db_config = ormConfig.Connections[name];
            if (db_config == null) {
                throw new OrmException("数据库[{0}], 未找到配置项", name);
            }
            if(string.IsNullOrEmpty(connectionString)) {
                connectionString = db_config.connectionString;
            }
            if(string.IsNullOrEmpty(connectionString)) {
                throw new OrmException("数据库[{0}], 连接字符串为空", db_config.name);
            }

            //
            this.Adapter = db_config.get_Adapter();
            this.ParamPrefix = this.Adapter.ParamPrefix;

            this.Provider = db_config.get_Factory();

            this.dbConn = this.Provider.CreateConnection();
            
            this.dbConn.ConnectionString = connectionString;

            this.Adapter.Conn = this.dbConn;

            this.table_prefix = 
                string.IsNullOrEmpty(db_config.table_prefix) ? "" : db_config.table_prefix;
            this.debug = OrmConfig.My.debug;
            this.trace = OrmConfig.My.trace;
        }
        /// <summary>
        /// 释放数据库资源
        /// </summary>
        public virtual void Dispose() {
            this.Close(true);
            this.dbConn = null;
        }
        #endregion Init & Dispose

        #region Control Commands

        bool debug { get; set; }
        bool trace { get; set; }
        string table_prefix { get; set; }

        public IDbAdapter Adapter { get; private set; }
        /// <summary>
        /// 命令参数前缀
        /// </summary>
        public string ParamPrefix {
            get;
            private set;
        }

        public DbProviderFactory Provider { get; private set; }
        DbConnection dbConn { get; set; }

        /// <summary>
        /// 当前数据库
        /// </summary>
        public string db {
            get {
                return this.dbConn.Database;
            }
            set {
                this.dbConn.ChangeDatabase(value);
            }
        }

        long connCounter = 0;
        /// <summary>
        /// 打开数据库连接
        /// </summary>
        public void Open() {
            this.connCounter += 1;
            if(this.connCounter > 1) {
                return;
            }

            this.dbConn.Open();
        }
        /// <summary>
        /// 关闭数据库连接
        /// </summary>
        public void Close() {
            this.Close(false);
        }
        /// <summary>
        /// 关闭数据库连接
        /// </summary>
        /// <param name="Force">是否强制关闭</param>
        public void Close(bool Force) {
            if(this.connCounter <= 0) {
                return;
            }

            this.connCounter--;
            if(this.connCounter == 0 || Force) {
                this.connCounter = 0;

                this.dbConn.Close();
            }
        }

        long transCounter = 0;
        DbTransaction dbTrans { get; set; }
        /// <summary>
        /// 开启事务
        /// </summary>
        public void Begin() {
            this.Begin(IsolationLevel.Unspecified);
        }
        /// <summary>
        /// 以指定的锁定行为开启事务
        /// </summary>
        /// <param name="level">锁定行为</param>
        public void Begin(IsolationLevel level) {
            this.transCounter++;
            if(this.transCounter > 1) {
                return;
            }

            this._exec_(this.show_trace("Trans_Begin", null, null), () => {
                this.dbTrans =
                    this.dbConn.BeginTransaction(level);
            });
        }
        /// <summary>
        /// 提交事务
        /// </summary>
        public void Commit() {
            if(this.transCounter <= 0) {
                return;
            }

            this.transCounter--;
            if(this.transCounter == 0) {
                this._exec_(this.show_trace("Trans_Commit", null, null), () => {
                    this.dbTrans.Commit();
                    this.dbTrans.Dispose();
                    this.dbTrans = null;
                });
            }
        }
        /// <summary>
        /// 回滚事务
        /// </summary>
        public void Rollback() {
            if(this.transCounter <= 0) {
                return;
            }

            this.transCounter = 0;
            this._exec_(this.show_trace("Trans_Rollback", null, null), () => {
                this.dbTrans.Rollback();
                this.dbTrans.Dispose();
                this.dbTrans = null;
            });
        }
        #endregion Control Commands

        #region Cmd Commands

        DbCommand dbCmd = null;
        /// <summary>
        /// 实例化数据库命令
        /// </summary>
        /// <param name="SQL">命令的SQL语句</param>
        /// <param name="IsProc">是否是存储过程</param>
        /// <param name="Params">命令参数（键、值对数组）</param>
        protected virtual void InitCmd(string SQL, bool IsProc, params object[] Params) {
            if(this.dbCmd == null) {
                this.dbCmd = this.dbConn.CreateCommand();
            }
            this.dbCmd.Transaction = this.dbTrans;

            this.dbCmd.Parameters.Clear();
            if(Params != null && Params.Length > 0) {
                if(Params.Length % 2 != 0) {
                    throw new OrmException("参数个数错误");
                }

                for(int i = 0, len = Params.Length; i < len; i += 2) {
                    string param_name = Params[i] as string;
                    if(string.IsNullOrEmpty(param_name)) {
                        throw new OrmException("参数名不能为空");
                    }
                    if(!param_name.StartsWith(this.ParamPrefix)) {
                        param_name = this.ParamPrefix + param_name;
                    }
                    object value = Params[i + 1];
                    if(value == null) {
                        value = DBNull.Value;
                    }
                    if(this.dbCmd.Parameters.Contains(param_name)) {
                        this.dbCmd.Parameters[param_name].Value = value;
                    } else {
                        DbParameter db_param = this.dbCmd.CreateParameter();
                        db_param.ParameterName = param_name;
                        db_param.Value = value;
                        this.dbCmd.Parameters.Add(db_param);
                    }
                }
            }

            this.dbCmd.CommandType = CommandType.Text;
            this.dbCmd.CommandText = SQL;
        }
        /// <summary>
        /// 命令超时时间
        /// </summary>
        public int CmdTimeOut { get; set; }
        /// <summary>
        /// 初始化数据库命令
        /// </summary>
        /// <param name="Cmd">IDbCmd</param>
        protected virtual void InitCmd(IDbCmd Cmd) {
            this.dbCmd = Cmd.Prepare(this.Adapter);
            this.dbCmd.Transaction = this.dbTrans;

            if(this.CmdTimeOut > 0) {
                this.dbCmd.CommandTimeout = this.CmdTimeOut;
            } else {
                this.CmdTimeOut = this.dbCmd.CommandTimeout;
            }

            this.LastCommand = this.dbCmd.CommandText;
        }

        protected virtual void InitCmd(DbCommand dbCmd) {
            this.dbCmd = dbCmd;
            this.dbCmd.Transaction = this.dbTrans;

            if(this.CmdTimeOut > 0) {
                this.dbCmd.CommandTimeout = this.CmdTimeOut;
            } else {
                this.CmdTimeOut = this.dbCmd.CommandTimeout;
            }

            this.LastCommand = this.dbCmd.CommandText;
        }
        #endregion Cmd Commands

        #region DDL
        /// <summary>
        /// 创建数据表
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="Tables">数据表名称</param>
        public virtual void Create<Tentity>(params string[] Tables)
            where Tentity : class, new() {
            this.Create<Tentity>(false, Tables);
        }
        /// <summary>
        /// 创建数据表
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="DropIfExists">如果存在则删除</param>
        /// <param name="Tables">数据表名称</param>
        public virtual void Create<Tentity>(bool DropIfExists, params string[] Tables)
            where Tentity : class, new() {
                if(Tables == null || Tables.Length == 0) {
                    string table_name = this.table_prefix + Class<Tentity>.Name;

                    this.try_exec(() => {
                        if(DropIfExists) {
                            this.Drop<Tentity>(true, Class<Tentity>.Name);
                        }
                        this.InitCmd(this.Adapter.PrepareCreate<Tentity>(table_name));
                        this._exec_(this.show_trace("CREATE", table_name, this.dbCmd), () => {
                            this.dbCmd.ExecuteNonQuery();
                        });
                    });
                } else {
                    this.try_exec(() => {
                        for(int i = 0, len = Tables.Length; i < len; i++) {
                            string table_i = this.table_prefix + Tables[i];

                            if(DropIfExists) {
                                this.Drop<Tentity>(true, Tables[i]);
                            }
                            this.InitCmd(this.Adapter.PrepareCreate<Tentity>(table_i));
                            this._exec_(this.show_trace("CREATE", table_i, this.dbCmd), () => {
                                this.dbCmd.ExecuteNonQuery();
                            });
                        }
                    });
                }
        }
        /// <summary>
        /// 删除数据表
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="Tables">数据表名称</param>
        public virtual void Drop<Tentity>(params string[] Tables) 
            where Tentity : class, new() {
            this.Drop<Tentity>(false, Tables);
        }
        /// <summary>
        /// 删除数据表
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="IfExists">如果存在则执行删除操作</param>
        /// <param name="Tables">数据表名称</param>
        public virtual void Drop<Tentity>(bool IfExists, params string[] Tables)
            where Tentity : class, new() {
                if(Tables == null || Tables.Length == 0) {
                    this.try_exec(() => {
                        string table_name = this.table_prefix + Class<Tentity>.Name;

                        this.InitCmd(this.Adapter.PrepareDrop<Tentity>(IfExists, table_name));
                        this._exec_(this.show_trace("DROP", table_name, this.dbCmd), () => {
                            this.dbCmd.ExecuteNonQuery();
                        });
                    });
                } else {
                    this.try_exec(() => {
                        for(int i = 0, len = Tables.Length; i < len; i++) {
                            string table_i = this.table_prefix + Tables[i];

                            this.InitCmd(this.Adapter.PrepareDrop<Tentity>(IfExists, table_i));
                            this._exec_(this.show_trace("DROP", table_i, this.dbCmd), () => {
                                this.dbCmd.ExecuteNonQuery();
                            });
                        }
                    });
                }
        }

        #endregion DDL

        #region Scalar
        /// <summary>
        /// 判断实体类记录是否存在
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="Tables">数据表名称</param>
        /// <returns>存在则返回True</returns>
        public virtual bool Exist<Tentity>(params string[] Tables) {
            return this.Count<Tentity>((Class<Tentity>.Where)null) > 0;
        }
        /// <summary>
        /// 按照指定条件判断实体记录是否存在
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="where">查询条件表达式</param>
        /// <param name="Tables">数据表名称</param>
        /// <returns>是否存在</returns>
        public virtual bool Exist<Tentity>(Class<Tentity>.Where where, params string[] Tables) {
            return this.Count<Tentity>(where) > 0;
        }
        /// <summary>
        /// 统计实体类记录数量
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="Tables">数据表名称</param>
        /// <returns>记录数量</returns>
        public virtual long Count<Tentity>(params string[] Tables) {
            return this.Count<Tentity>((Class<Tentity>.Where)null, Tables);
        }
        /// <summary>
        /// 按照指定条件判断实体类记录数量
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="where">条件表达式</param>
        /// <param name="Tables">数据表名称</param>
        /// <returns>记录数量</returns>
        public virtual long Count<Tentity>(Class<Tentity>.Where where, params string[] Tables) {

            Call<long, object> get_obj_count = (object objCount) => {
                if(objCount == null) {
                    return 0;
                } else if(objCount is int) {
                    return (int)objCount;
                } else if(objCount is long) {
                    return (long)objCount;
                }else if(objCount is decimal) {
                    return (long)(decimal)objCount;
                } else {
                    throw new OrmException("COUNT<T> Result Type Error:[{0}]", objCount.GetType());
                }
            };

            return this.try_exec<long>(() => {
                if(Tables == null || Tables.Length == 0) {
                    string table_name = this.table_prefix + Class<Tentity>.Name;

                    this.InitCmd(
                        this.Adapter.ToWhereString<Tentity>("Select Count(*) From " + table_name, where)
                        );
                    long counter = 0;
                    this._exec_(this.show_trace("COUNT", table_name, this.dbCmd), () => {
                        counter = get_obj_count(this.dbCmd.ExecuteScalar());
                    });
                    return counter;
                } else {
                    long counter = 0;
                    for(int i = 0, len = Tables.Length; i < len; i++) {
                        string table_i = this.table_prefix + Tables[i];

                        this.InitCmd(
                            this.Adapter.ToWhereString<Tentity>("Select Count(*) From " + table_i, where)
                            );
                        this._exec_(this.show_trace("COUNT", table_i, this.dbCmd), () => {
                            
                            counter += get_obj_count(this.dbCmd.ExecuteScalar());
                        });
                    }
                    return counter;
                }
            }, false);
        }
        /// <summary>
        /// 获取单一结果值
        /// </summary>
        /// <param name="SQL">SQL语句</param>
        /// <param name="Params">命令参数（键、值对数组）</param>
        /// <returns>结果值</returns>
        public virtual object GetObject(string SQL, object[] Params) {
            object obj_return = null;

            this.try_exec(() => {
                this.InitCmd(SQL, false, Params);
                this._exec_(this.show_trace("GET_OBJECT", "N/A", this.dbCmd), () => {
                    obj_return = this.dbCmd.ExecuteScalar();
                });
            });
            obj_return = 
                obj_return == DBNull.Value ? null : obj_return;
            return obj_return;
        }
        /// <summary>
        /// 获取单一结果值
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="SQL">SQL语句</param>
        /// <param name="Params">命令参数（键、值对数组）</param>
        /// <returns>结果值</returns>
        public virtual Tentity GetObject<Tentity>(string SQL, params object[] Params)  {
            return (Tentity)Class.Parse<Tentity>(this.GetObject(SQL, Params));
        }
        /// <summary>
        /// 数据库版本号
        /// </summary>
        public virtual string Version {
            get {
                return this.try_exec<string>(() => {
                    return this.dbConn.ServerVersion;
                }, false);
            }
        }
        /// <summary>
        /// 数据库当前时间
        /// </summary>
        public virtual DateTime Now {
            get {
                object obj_time = this.GetObject(this.Adapter.GetDateTime, null);
                if (obj_time is DateTime) {
                    return (DateTime)obj_time;
                } else if (obj_time is string) {
                    return DateTime.Parse((string)obj_time);
                } else {
                    throw new OrmException("DateTime Result Type Error");
                }
            }
        }
        #endregion Scalar

        #region I-D-U-Q

        #region I
        /// <summary>
        /// 将指定的实数据体插入数据表（表名默认为类名）
        /// </summary>
        /// <typeparam name="Tentity">数据实体类型</typeparam>
        /// <param name="entity">数据实体</param>
        /// <param name="tables">表名（如不指定则默认为类名）</param>
        /// <returns>受影响的记录条数，应为1</returns>
        public virtual int I<Tentity>(Tentity entity, params string[] tables)
            where Tentity : class, new() {
            int insert_counter = 0;

            IDbAdapter db_adapter = this.Adapter;
            List<Class<Tentity>.Property> fields = db_adapter.GetProperties<Tentity>();
            Exec<Tentity, DbCommand> params_copy = db_adapter.Get_I<Tentity>(fields);

            if(tables == null || tables.Length == 0) {
                this.try_exec(() => {
                    string table_name = this.table_prefix + Class<Tentity>.Name;

                    this.InitCmd(
                        db_adapter.PrepareInsert<Tentity>(table_name, fields)
                        );
                    
                    params_copy(entity, this.dbCmd);
                    this._exec_(this.show_trace("I", table_name, this.dbCmd), () => {
                        insert_counter = this.dbCmd.ExecuteNonQuery();
                    });
                });
            } else {
                this.try_exec(() => {
                    for(int i = 0, len = tables.Length; i < len; i++) {
                        string table_i = this.table_prefix + tables[i];

                        this.InitCmd(
                            db_adapter.PrepareInsert<Tentity>(table_i, fields)
                            );

                        params_copy(entity, this.dbCmd);
                        this._exec_(this.show_trace("I", table_i, this.dbCmd), () => {
                            insert_counter += this.dbCmd.ExecuteNonQuery();
                        });
                    }
                });
            }

            return insert_counter;
        }

        /// <summary>
        /// 将指定的实数据体集合插入数据表（表名默认为类名）
        /// </summary>
        /// <typeparam name="Tentity">数据实体类型</typeparam>
        /// <param name="entities">数据实体集合</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>受影响的记录行数，应等于数据实体集合数量</returns>
        public virtual int I<Tentity>(IList<Tentity> entities, params string[] tables)
            where Tentity : class, new() {
            int insert_counter = 0;

            IDbAdapter db_adapter = this.Adapter;
            List<Class<Tentity>.Property> fields = db_adapter.GetProperties<Tentity>();
            Exec<Tentity, DbCommand> params_copy = db_adapter.Get_I<Tentity>(fields);

            if(tables == null || tables.Length == 0) {
                this.try_exec(() => {
                    string table_name = this.table_prefix + Class<Tentity>.Name;

                    this.InitCmd(
                        db_adapter.PrepareInsert<Tentity>(table_name, fields)
                        );

                    DbCommand _dbCmd = this.dbCmd;
                    for(int j = 0, len_j = entities.Count; j < len_j; j++) {
                        params_copy(entities[j], _dbCmd);
                        this._exec_(this.show_trace("I", table_name, this.dbCmd), () => {
                            insert_counter += _dbCmd.ExecuteNonQuery();
                        });
                    }
                });
            } else {
                this.try_exec(() => {
                    for(int i = 0, len = tables.Length; i < len; i++) {
                        string table_i = this.table_prefix + tables[i];

                        this.InitCmd(
                            db_adapter.PrepareInsert<Tentity>(table_i, fields)
                            );

                        DbCommand _dbCmd = this.dbCmd;
                        for(int j = 0, len_j = entities.Count; j < len_j; j++) {
                            params_copy(entities[j], _dbCmd);
                            this._exec_(this.show_trace("I", table_i, this.dbCmd), () => {
                                insert_counter += _dbCmd.ExecuteNonQuery();
                            });
                        }
                    }
                });
            }

            return insert_counter;
        }
        #endregion I

        #region D
        /// <summary>
        /// 从数据表中删除指定的数据实体（数据表明默认为类名，数据实体必须包含主键或唯一键）
        /// </summary>
        /// <typeparam name="Tentity">数据实体类型</typeparam>
        /// <param name="entity">数据实体</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>受影响的记录行数</returns>
        public virtual int D<Tentity>(Tentity entity, params string[] tables)
            where Tentity : class, new() {

            Class<Tentity>.Where Where = null;
            List<Class<Tentity>.Property> Keys = this.Adapter.GetKeys<Tentity>();
            for(int i = 0, len = Keys.Count; i < len; i++) {
                Class<Tentity>.Property p_i = Keys[i];
                Where &= new Class<Tentity>.Where(p_i, "=", p_i.Get(entity));
            }
            if(Where == null) {
                throw new OrmException("Where Condition Is Null");
            }

            return this.D<Tentity>(Where, tables);
        }

        /// <summary>
        /// 从数据表中删除指定的数据实体
        /// </summary>
        /// <typeparam name="Tentity">数据实体类型</typeparam>
        /// <param name="Where">条件表达式</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>受影响的记录条数</returns>
        public virtual int D<Tentity>(Class<Tentity>.Where Where, params string[] tables)
            where Tentity : class, new() {
            int delete_counter = 0;

            IDbAdapter db_adapter = this.Adapter;
            if(tables == null || tables.Length == 0) {
                string table_name = this.table_prefix + Class<Tentity>.Name;

                this.InitCmd(this.Adapter.PrepareDelete<Tentity>(table_name, Where));

                this.try_exec(() => {
                    this._exec_(this.show_trace("D", table_name, this.dbCmd), () => {
                        delete_counter = this.dbCmd.ExecuteNonQuery();
                    });
                });
            } else {
                this.try_exec(() => {
                    for(int i = 0, len = tables.Length; i < len; i++) {
                        string table_i = this.table_prefix + tables[i];

                        this.InitCmd(this.Adapter.PrepareDelete<Tentity>(table_i, Where));
                        this._exec_(this.show_trace("D", table_i, this.dbCmd), () => {
                            delete_counter += this.dbCmd.ExecuteNonQuery();
                        });
                    }
                });
            }

            return delete_counter;
        }
        #endregion D

        #region U
        /// <summary>
        /// 更新指定的数据实体（数据实体必须有主键或唯一键）
        /// </summary>
        /// <typeparam name="Tentity">数据实体类型</typeparam>
        /// <param name="entity">数据实体</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>更新的记录条数</returns>
        public virtual int U<Tentity>(Tentity entity, params string[] tables)
            where Tentity : class, new() {
            return this.U<Tentity>(entity, this.Adapter.GetValues<Tentity>().ToArray(), this.Adapter.GetKeys<Tentity>().ToArray(), tables);
        }

        /// <summary>
        /// 更新指定的数据实体集合（数据实体必须有主键或唯一键）
        /// </summary>
        /// <typeparam name="Tentity">数据实体类型</typeparam>
        /// <param name="entities">数据实体集合</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>更新的记录条数</returns>
        public virtual int U<Tentity>(IList<Tentity> entities, params string[] tables)
            where Tentity : class, new() {
            return this.U<Tentity>(entities, this.Adapter.GetValues<Tentity>().ToArray(), this.Adapter.GetKeys<Tentity>().ToArray(), tables);
        }

        /// <summary>
        /// 按条件更新指定数据表中的数据
        /// </summary>
        /// <typeparam name="Tentity">数据实体类</typeparam>
        /// <param name="Set">更新表达式</param>
        /// <param name="Where">查询表达式</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>更新的记录条数</returns>
        public virtual int U<Tentity>(Class<Tentity>.Set Set, Class<Tentity>.Where Where, params string[] tables)
            where Tentity : class, new() {
            int update_counter = 0;
            if(tables == null || tables.Length == 0) {
                this.try_exec(() => {
                    string table_name = this.table_prefix + Class<Tentity>.Name;

                    this.InitCmd(this.Adapter.PrepareUpdate<Tentity>(table_name, Set, Where));
                    this._exec_(this.show_trace("U", table_name, this.dbCmd), () => {
                        update_counter = this.dbCmd.ExecuteNonQuery();
                    });
                });
            } else {
                this.try_exec(() => {
                    for(int i = 0, len = tables.Length; i < len; i++) {
                        string table_i = this.table_prefix + tables[i];

                        this.InitCmd(this.Adapter.PrepareUpdate<Tentity>(table_i, Set, Where));
                        this._exec_(this.show_trace("U", table_i, this.dbCmd), () => {
                            update_counter += this.dbCmd.ExecuteNonQuery();
                        });
                    }
                });
            }
            return update_counter;
        }
        /// <summary>
        /// 按指定的更新属性和条件属性更新实体实例
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="entity">实体实例</param>
        /// <param name="setProps">更新属性</param>
        /// <param name="whereProps">条件属性</param>
        /// <param name="tables">数据表</param>
        /// <returns>更新的记录数量</returns>
        public virtual int U<Tentity>(Tentity entity, Class<Tentity>.Property[] setProps, Class<Tentity>.Property[] whereProps, params string[] tables)
            where Tentity : class, new() {

            Class<Tentity>.Set Set = null;
            for(int i = 0, len = setProps.Length; i < len; i++) {
                Class<Tentity>.Property p_i = setProps[i];
                Set &= new Class<Tentity>.Set(p_i, "=", p_i.Get(entity));
            }
            if(Set == null) {
                throw new OrmException("Set Fields Is Null");
            }

            Class<Tentity>.Where Where = null;
            for(int i = 0, len = whereProps.Length; i < len; i++) {
                Class<Tentity>.Property p_i = whereProps[i];
                Where &= new Class<Tentity>.Where(p_i, "=", p_i.Get(entity));
            }
            if(Where == null) {
                throw new OrmException("Where Condition Is Null");
            }

            return this.U<Tentity>(Set, Where, tables);

        }
        /// <summary>
        /// 按指定的更新属性和条件属性更新实体实例集合
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="entities">实体实例集合</param>
        /// <param name="setProps">更新属性</param>
        /// <param name="whereProps">条件属性</param>
        /// <param name="tables">数据表</param>
        /// <returns>更新的记录数量</returns>
        public virtual int U<Tentity>(IList<Tentity> entities, Class<Tentity>.Property[] setProps, Class<Tentity>.Property[] whereProps, params string[] tables)
            where Tentity : class, new() {

            Class<Tentity>.Set Set = null;
            List<Class<Tentity>.Set> _Set = new List<Class<Tentity>.Set>();

            for(int i = 0, len = setProps.Length; i < len; i++) {
                Class<Tentity>.Property p_i = setProps[i];
                Class<Tentity>.Set s = new Class<Tentity>.Set(p_i, "=", Class.Default(p_i.pType));
                _Set.Add(s);
                Set &= s;
            }
            if(Set == null) {
                throw new OrmException("Set Fields Is Null");
            }

            Class<Tentity>.Where Where = null;
            List<Class<Tentity>.Where> _Where = new List<Class<Tentity>.Where>();
            for(int i = 0, len = whereProps.Length; i < len; i++) {
                Class<Tentity>.Property p_i = whereProps[i];
                Class<Tentity>.Where w = new Class<Tentity>.Where(p_i, "=", Class.Default(p_i.pType));
                _Where.Add(w);
                Where &= w;
            }
            if(Where == null) {
                throw new OrmException("Where Condition Is Null");
            }

            int update_counter = 0;

            Exec<string> update_table = (string table_name) => {
                this.InitCmd(this.Adapter.PrepareUpdate<Tentity>(table_name, Set, Where));

                for(int i = 0, len = entities.Count; i < len; i++) {
                    Tentity entity_i = entities[i];

                    for(int i_set = 0, len_i_set = _Set.Count; i_set < len_i_set; i_set++) {
                        Class<Tentity>.Set set_i = _Set[i_set];
                        Class<Tentity>.Property p = set_i.L as Class<Tentity>.Property;
                        set_i.R = p.Get(entity_i);
                    }
                    for(int i_where = 0, len_i_where = _Where.Count; i_where < len_i_where; i_where++) {
                        Class<Tentity>.Where where_i = _Where[i_where];
                        Class<Tentity>.Property p = where_i.L as Class<Tentity>.Property;
                        where_i.R = p.Get(entity_i);
                    }
                    this._exec_(this.show_trace("U", table_name, this.dbCmd), () => {
                        update_counter += this.dbCmd.ExecuteNonQuery();
                    });
                }
            };

            if(tables == null || tables.Length == 0) {
                this.try_exec(() => {
                    update_table(this.table_prefix + Class<Tentity>.Name);
                });
            } else {
                this.try_exec(() => {
                    for(int i = 0, len = tables.Length; i < len; i++) {
                        update_table(this.table_prefix + tables[i]);
                    }
                });
            }

            return update_counter;
        }
        #endregion U

        #region Q
        /// <summary>
        /// 按条件从指定的数据表中查询单一结果值
        /// </summary>
        /// <typeparam name="Tentity">数据实体类</typeparam>
        /// <param name="where">查询表达式</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>查询到的数据实体，如无结果则为null,如有多个结果值则报错</returns>
        public virtual Tentity Q<Tentity>(Class<Tentity>.Where where, params string[] tables)
            where Tentity : class, new() {
            List<Tentity> container = new List<Tentity>();

            this.Q<Tentity>(container, where, tables);

            if(container.Count == 0) {
                return null;
            } else if(container.Count > 1) {
                throw new OrmException("记录条数多余一个[{0}]", container.Count);
            } else {
                return container[0];
            }
        }

        /// <summary>
        /// 查询全表至指定的结果集
        /// </summary>
        /// <typeparam name="Tentity">数据实体类</typeparam>
        /// <param name="container">结果集</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>查询到的记录条数</returns>
        public virtual int Q<Tentity>(IList<Tentity> container, params string[] tables)
            where Tentity : class, new() {
                return this.Q<Tentity>(container, (Class<Tentity>.Where)null, tables);
        }

        /// <summary>
        /// 按条件查询数据至指定的结果集
        /// </summary>
        /// <typeparam name="Tentity">数据实体类</typeparam>
        /// <param name="container">结果集</param>
        /// <param name="where">条件表达式</param>
        /// <param name="tables">表名（如不指定则默认为数据实体类名）</param>
        /// <returns>查询到的记录条数</returns>
        public virtual int Q<Tentity>(IList<Tentity> container, Class<Tentity>.Where where, params string[] tables)
            where Tentity : class, new() {

            IDbAdapter db_adapter = this.Adapter;
            List<Class<Tentity>.Property> fields = this.Adapter.GetProperties<Tentity>();
            Exec<DbDataReader, Tentity> result_copy = db_adapter.Get_Q<Tentity>(fields);

            int query_counter=0;

            if(tables == null || tables.Length == 0) {
                this.try_exec(() => {
                    string table_name = this.table_prefix + Class<Tentity>.Name;

                    this.InitCmd(db_adapter.PrepareQuery<Tentity>(0, fields, table_name , where, null));
                    this._exec_(this.show_trace("Q", table_name, this.dbCmd), () => {
                        DbDataReader reader = this.dbCmd.ExecuteReader();

                        try {
                            query_counter = this.Fetch<Tentity>(reader, result_copy, container);
                        } finally {
                            reader.Close();
                        }
                    });
                });
            } else {
                this.try_exec(() => {
                    for(int i = 0, len = tables.Length; i < len; i++) {
                        string table_i = this.table_prefix + tables[i];

                        this.InitCmd(db_adapter.PrepareQuery<Tentity>(0, fields, table_i, where, null));
                        this._exec_(this.show_trace("Q", table_i, this.dbCmd), () => {
                            DbDataReader reader = this.dbCmd.ExecuteReader();
                            try {
                                query_counter = this.Fetch<Tentity>(reader, result_copy, container);
                            } finally {
                                reader.Close();
                            }
                        });
                    }
                });
            }

            return query_counter;
        }

        /// <summary>
        /// 依据SQL语句查询数据至指定的结果集
        /// </summary>
        /// <typeparam name="Tentity">数据实体类</typeparam>
        /// <param name="SQL">SQL语句</param>
        /// <param name="container">结果集</param>
        /// <param name="Qcopy">复制代理（默认不指定）</param>
        /// <param name="Params">SQL语句参数</param>
        /// <returns>查询结果集条数</returns>
        public virtual int Q<Tentity>(string SQL, IList<Tentity> container, Exec<DbDataReader, Tentity> Qcopy = null, params object[] Params)
            where Tentity : class, new() {

            int query_counter = 0;
            this.InitCmd(SQL, false, Params);

            this.try_exec(() => {
                this._exec_(this.show_trace("Q_SQL", null, this.dbCmd), () => {
                    DbDataReader reader = this.dbCmd.ExecuteReader();
                    try {
                        query_counter =
                            Qcopy == null ? this.Fetch<Tentity>(reader, container) : this.Fetch<Tentity>(reader, Qcopy, container);
                    } finally {
                        reader.Close();
                    }
                });
            });
            return query_counter;
        }
        #endregion Q

        #endregion I-D-U-Q
        /// <summary>
        /// 执行SQL语句
        /// </summary>
        /// <param name="SQL">SQL语句</param>
        /// <param name="IsProc">是否是存储过程</param>
        /// <param name="Params">命令参数（键、值对数组）</param>
        /// <returns>受影响的记录条数</returns>
        public virtual int Exec(string SQL, bool IsProc = false, params object[] Params) {

            int result = -1;
            this.InitCmd(SQL, IsProc, Params);
            
            this.try_exec(() => {
                this._exec_(this.show_trace("Exec", null, this.dbCmd), () => {
                    result = this.dbCmd.ExecuteNonQuery();
                });
            });

            return result;
        }

        #region E I-D-U-Q
        /// <summary>
        /// 执行新增操作
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="I">新增表达式</param>
        /// <returns>新增的记录数</returns>
        public virtual int E<Tentity>(Class<Tentity>.I I)
            where Tentity : class, new() {

            int counter = 0;

            this.InitCmd(I);
            Exec<Tentity, DbCommand> params_copy = I.Pcopy;

            this.try_exec(() => {
                List<Tentity> values = I.values;
                for (int i = 0, len = values.Count; i < len; i++) {
                    Tentity value_i = values[i];
                    params_copy(value_i, this.dbCmd);
                    this._exec_(this.show_trace("E_I", I.table_name, this.dbCmd), () => {
                        counter += this.dbCmd.ExecuteNonQuery();
                    });
                }
            });

            return counter;
        }
        /// <summary>
        /// 执行删除操作
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="D">删除表达式</param>
        /// <returns>删除的记录数</returns>
        public virtual int E<Tentity>(Class<Tentity>.D D)
            where Tentity : class, new() {
            this.InitCmd(D);

            return this.try_exec<int>(() => {
                int result_counter = 0;
                this._exec_(this.show_trace("E_D", D.table_name, this.dbCmd), () => {
                    result_counter = this.dbCmd.ExecuteNonQuery();
                });
                return result_counter;
            }, false);
        }
        /// <summary>
        /// 执行更新操作
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="U">更新记录数</param>
        /// <returns>更新的记录数</returns>
        public virtual int E<Tentity>(Class<Tentity>.U U)
            where Tentity : class, new() {
            this.InitCmd(U);

            return this.try_exec<int>(() => {
                int result_counter = 0;
                this._exec_(this.show_trace("E_U", U.table_name, this.dbCmd), () => {
                    result_counter = this.dbCmd.ExecuteNonQuery();
                });
                return result_counter;
            }, false);
        }
        /// <summary>
        /// 执行查询操作
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="Q">查询表达式</param>
        /// <param name="Container">查询结果集</param>
        /// <returns>查询到的记录数</returns>
        public virtual int E<Tentity>(Class<Tentity>.Q Q, IList<Tentity> Container)
            where Tentity : class, new() {

                return this.try_exec<int>(() => {
                    this.InitCmd(Q);
                    int resultCounter = 0;

                    DbDataReader reader = this.dbCmd.ExecuteReader();
                    try {
                        this._exec_(this.show_trace("E_Q", Q.table_name, this.dbCmd), () => {
                            resultCounter = this.Fetch<Tentity>(reader, Q.Qcopy, Container);
                        });
                    } finally {
                        reader.Close();
                    }

                    return resultCounter;
                }, false);
        }
        #endregion E I-D-U-Q

        #region Helpers
        /// <summary>
        /// 获取结果集
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="reader">DataReader</param>
        /// <param name="container">查询结果集合</param>
        /// <returns>查询到的记录数</returns>
        public virtual int Fetch<Tentity>(DbDataReader reader, IList<Tentity> container)
            where Tentity : class, new() {

            List<Class<Tentity>.Property> P = new List<Class<Tentity>.Property>();
            for(int i = 0, len = reader.FieldCount; i < len; i++) {
                string f_name = reader.GetName(i);
                Class<Tentity>.Property p = Class<Tentity>.GetProperty(f_name);
                if(p == null) {
                    throw new OrmException("属性未找到【{0}】", f_name);
                }

                P.Add(p);
            }

            return this.Fetch<Tentity>(reader, this.Adapter.Get_Q<Tentity>(P), container);
        }
        /// <summary>
        /// 获取结果集
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="reader">DataReader</param>
        /// <param name="P">实体类属性</param>
        /// <param name="container">查询结果集合</param>
        /// <returns>查询到的记录数</returns>
        protected virtual int Fetch<Tentity>(DbDataReader reader, Class<Tentity>.Property[] P, IList<Tentity> container)
            where Tentity : class, new() {
            return this.Fetch<Tentity>(reader, this.Adapter.Get_Q<Tentity>(P), container);
        }
        /// <summary>
        /// 获取结果集
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="reader">DataReader</param>
        /// <param name="Qcopy">记录复制代理</param>
        /// <param name="container">查询结果集</param>
        /// <returns></returns>
        protected virtual int Fetch<Tentity>(DbDataReader reader, Exec<DbDataReader, Tentity> Qcopy, IList<Tentity> container)
            where Tentity : class, new() {

            if(this.debug) {
                this.show_debug<Tentity>(reader);
            }

            int counter = 0;

            do {
                while (reader.Read()) {
                    Tentity dtoNew = new Tentity();
                    Qcopy(reader, dtoNew);
                    container.Add(dtoNew);

                    counter += 1;
                }
            } while (reader.NextResult());

            return counter;
        }

        #endregion Helpers
        string LastCommand = null;
        /// <summary>
        /// 返回最后一条SQL语句
        /// </summary>
        /// <returns>最后一条SQL语句</returns>
        public override string ToString() {
            if(string.IsNullOrEmpty(this.LastCommand)) {
                return "--No Command";
            }

            return this.LastCommand;
        }
        /// <summary>
        /// 通过Console输出调试信息
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="reader">DbDataReader</param>
        protected virtual void show_debug<Tentity>(DbDataReader reader) {
            StringBuilder sbTypes = new StringBuilder();
            sbTypes.Append("Field Type:").Append(Class<Tentity>.FullName + "\r\n");
            for(int i = 0, len = reader.FieldCount; i < len; i++) {
                sbTypes.AppendFormat("{0}:{1}\r\n", reader.GetName(i), reader.GetFieldType(i).Name);
            }
            System.Console.WriteLine(sbTypes.ToString());
        }

        int session_id = -1;
        /// <summary>
        /// SQL语句追踪事件（当命令执行后触发）
        /// </summary>
        public event OrmTraceDelegate OnTrace;
        Exec<Exception> show_trace(string action, string table, DbCommand dbCmd) {
            if(!this.trace) {
                return null;
            }

            int session_id = this.session_id;
            string cmd_text = dbCmd.CommandText;
            if(this.OnTrace != null) {
                return this.OnTrace(session_id, action, table, cmd_text, this.dbCmd.Parameters);

            } else {
                return null;
            }
        }
        /// <summary>
        /// 绑定实体集合（监控其更改，自动完成增删改查）
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="entities">实体集合</param>
        public void Bind<Tentity>(CollectionBase<Tentity> entities)
            where Tentity : class, INotifyPropertyChanged, new() {

            CollectionBase<Tentity> dataCache = new CollectionBase<Tentity>();
            dataCache.Add(entities);

            entities.ListChanged +=
                new ListChangedEventHandler((object sender, ListChangedEventArgs e) => {

                    switch (e.ListChangedType) {
                        case ListChangedType.ItemAdded:
                            lock (entities) {
                                this.I<Tentity>(entities[e.NewIndex]);
                                if (e.NewIndex == dataCache.Count) {
                                    dataCache.Add(entities[e.NewIndex]);
                                } else {
                                    dataCache.Insert(e.NewIndex, entities[e.NewIndex]);
                                }
                            }
                            break;
                        case ListChangedType.ItemDeleted:
                            lock (entities) {
                                try {
                                    this.D<Tentity>(dataCache[e.NewIndex]);
                                } finally {
                                    dataCache.RemoveAt(e.NewIndex);
                                }
                            }

                            break;
                        case ListChangedType.ItemChanged:
                            Class<Tentity>.Property p_changed =
                                Class<Tentity>.GetProperty(e.PropertyDescriptor.Name);
                            if (p_changed == null) {
                                throw new OrmException("属性未找到[{0}]", e.PropertyDescriptor.Name);
                            }
                            lock (entities) {
                                this.U<Tentity>(dataCache[e.NewIndex], p_changed, this.Adapter.GetKeys<Tentity>().ToArray());
                            }

                            break;
                        case ListChangedType.ItemMoved:
                            lock (entities) {
                                Tentity data_temp = dataCache[e.OldIndex];
                                dataCache[e.OldIndex] = dataCache[e.NewIndex];
                                dataCache[e.NewIndex] = data_temp;
                            }
                            break;
                        default:
                            break;
                    }
                });
        }
        /// <summary>
        /// 绑定实体实例（监控其更改，自动完成增删改查）
        /// </summary>
        /// <typeparam name="Tentity">实体类型</typeparam>
        /// <param name="entity">实体实例</param>
        public void Bind<Tentity>(Tentity entity)
            where Tentity: class, INotifyPropertyChanged, new() {

                Class<Tentity>.Property[] _keys = this.Adapter.GetKeys<Tentity>().ToArray();
            if (_keys == null || _keys.Length == 0) {
                throw new OrmException("No Primary Keys To Bind. Type:[{0}]", Class<Tentity>.FullName);
            }

            entity.PropertyChanged += (object sender, PropertyChangedEventArgs e) => {
                Class<Tentity>.Property p_changed = Class<Tentity>.GetProperty(e.PropertyName);
                if (p_changed == null) {
                    throw new OrmException("Property[{0}] Not Found In Type[{1}]", e.PropertyName, Class<Tentity>.FullName);
                }
                lock (entity) {
                    this.U<Tentity>(entity, _keys, new Class<Tentity>.Property[] { p_changed });
                }
            };
        }

        void _exec_(Exec<Exception> after_exec, Exec worker) {
            try {
                worker();
            } catch(Exception ex) {
                if(after_exec != null) {
                    after_exec(ex);
                } else {
                    throw ex;
                }
            }
        }
        /// <summary>
        /// 执行数据库命令
        /// </summary>
        /// <param name="do_work">命令代理</param>
        /// <param name="IsTrans">是否启用事务</param>
        public void try_exec(Exec do_work, bool IsTrans = false) {
            this.Open();
            try {
                if(IsTrans) {
                    this.Begin();
                }
                do_work();
                if(IsTrans) {
                    this.Commit();
                }
            } catch(Exception ex) {
                if(IsTrans) {
                    this.Rollback();
                }
                throw ex;
            } finally {
                this.Close();
            }
        }
        /// <summary>
        /// 执行数据库命令并返回结果
        /// </summary>
        /// <typeparam name="T">返回值类型</typeparam>
        /// <param name="do_work">命令代理</param>
        /// <param name="IsTrans">是否启用事务</param>
        /// <returns>结果值</returns>
        public T try_exec<T>(Call<T> do_work, bool IsTrans) {
            this.Open();
            try {
                if (IsTrans) {
                    this.Begin();
                }
                T result = do_work();
                if (IsTrans) {
                    this.Commit();
                }
                return result;
            } catch (Exception ex) {
                if (IsTrans) {
                    this.Rollback();
                }

                throw ex;
            } finally {
                this.Close();
            }
        }
    }
}
